﻿namespace BusinessLayer.Tools
{
    using System;
    using System.IO;
    using System.Security;

    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;

    /// <summary>
    ///     Class BasicFileLogger
    /// </summary>
    public class CustomLogger : Logger
    {
        #region Fields

        private StreamWriter _streamWriter;

        private readonly int _indent; 

        #endregion

        public CustomLogger()
        {
            _indent = 0;
        }

        #region Public Methods and Operators

        /// <summary>
        ///     Initialize is guaranteed to be called by MSBuild at the start of the build
        ///     before any events are raised.
        /// </summary>
        /// <param name="eventSource">The available events that a logger can subscribe to.</param>
        /// <exception cref="Microsoft.Build.Framework.LoggerException">
        ///     Log file was not set.
        ///     or
        ///     Log file was not set.
        ///     or
        ///     Too many parameters passed.
        ///     or
        ///     Failed to create log file:  + ex.Message
        /// </exception>
        public override void Initialize(IEventSource eventSource)
        {
            // The name of the log file should be passed as the first item in the  
            // "parameters" specification in the /logger switch.  It is required 
            // to pass a log file to this logger. Other loggers may have zero or more than   
            // one parameters.  
            if (null == Parameters)
            {
                throw new LoggerException("Log file was not set.");
            }

            string[] parameters = Parameters.Split(';');

            string logFile = parameters[0];
            if (string.IsNullOrEmpty(logFile))
            {
                throw new LoggerException("Log file was not set.");
            }

            if (parameters.Length > 1)
            {
                throw new LoggerException("Too many parameters passed.");
            }

            if (eventSource == null)
            {
                throw new ArgumentException("eventSource");
            }

            try
            {
                // Open the file  
                _streamWriter = new StreamWriter(logFile);
            }
            catch (Exception ex)
            {
                if (ex is UnauthorizedAccessException || ex is ArgumentNullException || ex is PathTooLongException
                    || ex is DirectoryNotFoundException || ex is NotSupportedException || ex is ArgumentException
                    || ex is SecurityException || ex is IOException)
                {
                    throw new LoggerException("Failed to create log file: " + ex.Message);
                }

                // Unexpected failure  
                throw;
            }

            // For brevity, we'll only register for certain event types. Loggers can also  
            // register to handle TargetStarted/Finished and other events. 
            eventSource.MessageRaised += EventSourceMessageRaised;
        }

        /// <summary>
        ///     Shutdown() is guaranteed to be called by MSBuild at the end of the build, after all
        ///     events have been raised.
        /// </summary>
        public override void Shutdown()
        {
            // Done logging, let go of the file 
            _streamWriter.Close();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Just write a line to the log
        /// </summary>
        /// <param name="line">The line.</param>
        /// <param name="e">The <see cref="BuildEventArgs"/> instance containing the event data.</param>
        private void WriteLine(string line, BuildEventArgs e)
        {
            for (int i = _indent; i > 0; i--)
            {
                _streamWriter.Write("\t");
            }

            _streamWriter.WriteLine(line + e.Message);
        }

        /// <summary>
        /// Write a line to the log, adding the SenderName and Message
        /// (these parameters are on all MSBuild event argument objects)
        /// </summary>
        /// <param name="line">The line.</param>
        /// <param name="e">The <see cref="BuildEventArgs"/> instance containing the event data.</param>
        private void WriteLineWithSenderAndMessage(string line, BuildEventArgs e)
        {
            if (0 == String.Compare(e.SenderName, "MSBuild", StringComparison.OrdinalIgnoreCase))
            {
                // Well, if the sender name is MSBuild, let's leave it out for prettiness 
                WriteLine(line, e);
            }
            else
            {
                WriteLine(e.SenderName + ": " + line, e);
            } 
        }

        private void EventSourceMessageRaised(object sender, BuildMessageEventArgs e)
        {
            WriteLineWithSenderAndMessage(string.Empty, e);
            /*// BuildMessageEventArgs adds Importance to BuildEventArgs  
            // Let's take account of the verbosity setting we've been passed in deciding whether to log the message  
            if ((e.Importance == MessageImportance.High && IsVerbosityAtLeast(LoggerVerbosity.Minimal))
                || (e.Importance == MessageImportance.Normal && IsVerbosityAtLeast(LoggerVerbosity.Normal))
                || (e.Importance == MessageImportance.Low && IsVerbosityAtLeast(LoggerVerbosity.Detailed)))
            {
                WriteLineWithSenderAndMessage(string.Empty, e);
            }*/
        }

        #endregion
    }
}